/*
 	 Instituto Politécnico de Beja
         Escolha Superior deTecnologia e Gestão
         Mestrado em Engenharia de Segurança Informática
         Conceitos de Programação para a Segurança
Titulo:  Gerador de Números Pseudo-Aleatórios em C
Docente: Professor Doutor José Jasnau Caeiro
Autores: Daniel Franco nº 12062
         Manuel André Martins nº 12056 
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>



/*

função que gera umaTabela com 1000 posições e a preenche com números aleatórios entre 0 e 9
o número de cada digito é sempre igual, pelo que cada digito aparece 100 vezes
esta última condição é garantida pelo ciclo while que contabiliza o número de vezes que
cada digito vai aparecendo.
*/
int p;
int T[100000];

void criar_tabela()
{
	int tabela[1000];
        int i, digito, 
	pos,  
	cont_digito0,
	cont_digito1, 
	cont_digito2, 
	cont_digito3, 
	cont_digito4, 
	cont_digito5, 
	cont_digito6, 
	cont_digito7, 
	cont_digito8, 
	cont_digito9;
        i=0;
        digito=0;
        pos=0;
        cont_digito0=0; 
	cont_digito1=0; 
	cont_digito2=0; 
	cont_digito3=0; 
	cont_digito4=0; 
	cont_digito5=0; 
	cont_digito6=0; 
	cont_digito7=0; 
	cont_digito8=0; 
	cont_digito9=0;
        
//inicializa a T a zeros
	for(i=0 ; i<1000 ; i++)
        {
              T[i] = 0;
        }
        while (pos < 1000)
        {
                digito = (rand() % 10);
                if (digito == 0 && cont_digito0 < 100)
                {              
                        cont_digito0 ++;
                        T[pos] = digito;              
                }
                if (digito == 1 && cont_digito1 < 100)
                {              
                        cont_digito1 ++;
                        T[pos] = digito;              
                }
                if (digito == 2 && cont_digito2 < 100)
                {              
                        cont_digito2 ++;
                        T[pos] = digito;              
                }

                if (digito == 3 && cont_digito3 < 100)
                {              
                       cont_digito3 ++;
                       T[pos] = digito;              
                }      
               if (digito == 4 && cont_digito4 < 100)
                {              
                        cont_digito4 ++;
                        T[pos] = digito;              
                }
                if (digito == 5 && cont_digito5 < 100)
                {              
                        cont_digito5 ++;
                        T[pos] = digito;              
                }      
                if (digito == 6 && cont_digito6 < 100)
                {              
                        cont_digito6 ++;
                        T[pos] = digito;              
                }
                if (digito == 7 && cont_digito7 < 100)
                {              
                        cont_digito7 ++;
                        T[pos] = digito;              
                }
                if (digito == 8 && cont_digito8 < 100)
                {              
                        cont_digito8 ++;
                        T[pos] = digito;              
                }
                if (digito == 9 && cont_digito9 < 100)
                {              
                        cont_digito9 ++;
                        T[pos] = digito;              
                }
                pos++;
		
        }
		/*return T;*/
	

}



/*
Função que devolve um número aleatório entre 0 e 999
*/

int calculo_p()
{
        int p = 0;
        p = (rand() % 999);
        return p;
}


/*
Função que permuta o valor em T[l] com o valor em T[0]
*/

void permuta(int l)
{
        int auxiliar = 0;
        auxiliar = T[l];
        T[l] = T[0];
        T[0] = auxiliar;
}


/*

Função que gera o novo valor de p

*/

int novo_p(int z_1, int z_2, int z_3, int z_4)

{      
	p = (z_1 * 100) + (z_2 * 10) + (z_3 * 1);
	return p;
}      


/*

Função Main - 
*/

int main()
{
        
       /* variável que armazena um pseudo-aleatório entre 0 e 999 * /
        /*calcula quantos numeros a gerar*/
	int t1 = clock();
        criar_tabela();
	p = calculo_p();	
	int l=0;
	int iteracoes = 1000;
        int z1 = 0;
	int z2 = 0;
	int z3 = 0;
	int z4 = 0;
	int Nk = 0;
	int t2 = 0;	

while (iteracoes > 0 )
{

	if (p < 1000)
	{
	   l = p;
           z1 = T[l];
	}
	
	if (p >= 1000)
	{
	   l = 0;
           z1 = T[l];
	}
	permuta(l);	
	
	if (p < 999)
	{
	   l = p+1;
           z2 = T[l];
	}
	
	if (p >= 999)
	{
	   l = 0;
           z2 = T[l];
	}
	permuta(l);
	
	if (p < 998)
	{
	   l = p+2;
           z3 = T[l];
	}
	
	if (p >= 998)
	{
	   l = 0;
           z3 = T[l];
	}
	permuta(l);
	
	if (p < 997)
	{
	   l = p+3;
           z4 = T[l];
	}
	
	if (p >= 997)
	{
	   l = 0;
           z4 = T[l];
	}
	permuta(l);


	Nk = z1 << 12 | z2 << 8 | z3 << 4 | z4;

                printf("Número N: %d\n\n", Nk);
                p = novo_p(z1, z2, z3, z4);
                iteracoes = iteracoes -1;
}   	
	

	t2 = clock();
        printf ("t1: %d\n\n", t1);
        printf ("t2: %d\n\n", t2);
        printf("Executou em %.4lf segundos\n", (t2-t1)/(double)CLOCKS_PER_SEC);
        return 0;      	
      
}
/*
Resultados dos tempos obtidos:
MacBook Pro Intel Core 2 Duo 2,26Ghz - 8GB DDRIII

10    Números: 0 segundos
100   Números: 0,01 segundos
1000  Números: 0,01 segundos
10000 Números: 0,01 segundos
*/
